package server.threads;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

import server.beans.MessageBean;
import server.constants.IncomingConstants;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import server.GameServer;

/**
 * This thread is used by a GameServer to handle any incoming messages from a user
 * that is currently in the game. This includes an attempt to kick, move, select
 * team, and leave. One GameServerIncoming Thread maps to one user in the game.
 */
public class GameServerIncoming extends Thread {
	private Socket socket;
	private BufferedReader in;
	private GameServer gameServer;
	
	/**
	 * Allocates a new GameServerIncoming thread object.
	 * @param name the name of the player that the thread is listening to for messages
	 * @param socket the Socket connection of the player
	 * @param gameServer a reference to GameServer to perform actions based on messages
	 */
	public GameServerIncoming(String name, Socket socket, GameServer gameServer) {
		super(name);
		this.socket = socket;
		this.gameServer = gameServer;
		
		try {
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void run() {
		String incomingMsg = "";
					
		try {
			while((incomingMsg = in.readLine()) != null){				
				//System.out.println("GameServer " + gameServer.getName() + " received: " + incomingMsg + " from " + socket.getInetAddress() + ":" + socket.getPort());
				
				// Parse the json message to obtain the message type 
				Gson gson = new Gson();
		        MessageBean bean = gson.fromJson(incomingMsg, MessageBean.class);
				
				if(bean.getType() == IncomingConstants.KICK) {
					//System.out.println("GameServer " + gameServer.getName() + ": kick");
					gameServer.getGameModel().performKick(getName());
					gameServer.getGameModel().performBallMove();
				}
				else if(bean.getType() == IncomingConstants.MOVE) {
					//System.out.println("GameServer " + gameServer.getName()  + ": move, x: " + bean.getGameDetails().getX() + ", y: " + bean.getGameDetails().getY());
					gameServer.getGameModel().performMove(getName(), bean.getGameDetails().getX(), bean.getGameDetails().getY());
					gameServer.getGameModel().performBallMove();
					
				}
				else if(bean.getType() == IncomingConstants.SELECT_TEAM) {
					// Only the admin is allowed to switch a player's team
					if(this.getName().equals(gameServer.getAdmin())) {
						System.out.println("GameServer " + gameServer.getName() + ": select team, player: " + bean.getGameDetails().getName() + ", team: " + bean.getGameDetails().getTeam());
						gameServer.getGameModel().changeTeam(getName(), bean.getGameDetails().getTeam()) ;
					}
				}
				else if(bean.getType() == IncomingConstants.INCREASE_TIME) {
					// Only the admin is allowed to increase time
					if(getName().equals(gameServer.getAdmin())) {
						System.out.println("GameServer " + gameServer.getName() + ": increase time, limit: " + bean.getGameDetails().getTimeLimit());
						gameServer.getGameModel().changeTimeLimit(bean.getGameDetails().getTimeLimit());
					}
				}
				else if(bean.getType() == IncomingConstants.INCREASE_SCORE) {
					// Only the admin is allowed to increase score limit
					if(this.getName().equals(gameServer.getAdmin())) {
						System.out.println("GameServer " + gameServer.getName() + ": increase score, limit: " + bean.getGameDetails().getScoreLimit());
						gameServer.getGameModel().changeMaxScore(bean.getGameDetails().getScoreLimit());
					}
				}
				else if(bean.getType() == IncomingConstants.LEAVE) {
					System.out.println("GameServer " + gameServer.getName() + ": leave, player: " + getName());
					gameServer.getGameModel().removePlayer(getName());
					gameServer.removePlayer(getName(), true);
					break;
				}
				else {
					// TODO: error handling for invalid message
				}
			}
		} catch (IOException e) {
			// If someone leaves while the game is in progress, this exception is thrown
			gameServer.removePlayer(getName(), false);
		} catch (JsonSyntaxException e) {
			System.out.println("Error: JSON Message could not be parsed");
		}
		
		System.out.println("Thread destroyed");
	}
}
